#include "SQLForeignKeyImpl.h"

// #include "../../../utils/enumimpl.h"
#include "../../visitor/SQLASTVisitor.h"
#include "../../../utils/listTran.h"
#include "../../../utils/StringUtils.h"
#include "SQLExprTableSource.h"

SQLForeignKeyImpl_Match SQLForeignKeyImpl_Match::FULL = SQLForeignKeyImpl_Match(1 << 1, make_string_ptr("FULL"));
SQLForeignKeyImpl_Match SQLForeignKeyImpl_Match::PARTIAL = SQLForeignKeyImpl_Match(1 << 2, make_string_ptr("PARTIAL"));
SQLForeignKeyImpl_Match SQLForeignKeyImpl_Match::SIMPLE = SQLForeignKeyImpl_Match(1 << 3, make_string_ptr("SIMPLE"));

SQLForeignKeyImpl_Match::SQLForeignKeyImpl_Match(uint64_t mask, string_ptr name)
{
  this->name = name;
  this->nameLCase = StringUtils::toLower(name);
  this->mask = mask;
}

SQLForeignKeyImpl_On SQLForeignKeyImpl_On::DELETE = SQLForeignKeyImpl_On(1 << 1, make_string_ptr("DELETE"));
SQLForeignKeyImpl_On SQLForeignKeyImpl_On::UPDATE = SQLForeignKeyImpl_On(1 << 2, make_string_ptr("UPDATE"));

SQLForeignKeyImpl_On::SQLForeignKeyImpl_On(uint64_t mask, string_ptr name)
{
  this->name = name;
  this->nameLCase = StringUtils::toLower(name);
  this->mask = mask;
}

SQLForeignKeyImpl_Option SQLForeignKeyImpl_Option::RESTRICT = SQLForeignKeyImpl_Option(1 << 1, make_string_ptr("RESTRICT"));
SQLForeignKeyImpl_Option SQLForeignKeyImpl_Option::CASCADE = SQLForeignKeyImpl_Option(1 << 2, make_string_ptr("CASCADE"));
SQLForeignKeyImpl_Option SQLForeignKeyImpl_Option::SET_NULL = SQLForeignKeyImpl_Option(1 << 3, make_string_ptr("SET NULL"));
SQLForeignKeyImpl_Option SQLForeignKeyImpl_Option::NO_ACTION = SQLForeignKeyImpl_Option(1 << 4, make_string_ptr("NO ACTION"));
SQLForeignKeyImpl_Option SQLForeignKeyImpl_Option::SET_DEFAULT = SQLForeignKeyImpl_Option(1 << 5, make_string_ptr("SET DEFAULT"));

SQLForeignKeyImpl_Option::SQLForeignKeyImpl_Option(uint64_t mask, string_ptr name)
{
  this->name = name;
  this->nameLCase = StringUtils::toLower(name);
  this->mask = mask;
}

SQLForeignKeyImpl::SQLForeignKeyImpl()
{
  referencingColumns = std::make_shared<std::list<SQLName_ptr>>();
  referencedColumns = std::make_shared<std::list<SQLName_ptr>>();
}

SQLName_list_ptr SQLForeignKeyImpl::getReferencingColumns()
{
  return referencingColumns;
}

SQLExprTableSource_ptr SQLForeignKeyImpl::getReferencedTable()
{
  return referencedTable;
}

SQLName_ptr SQLForeignKeyImpl::getReferencedTableName()
{
  if (referencedTable == NULL)
  {
    return NULL;
  }
  return referencedTable->getName();
}

void SQLForeignKeyImpl::setReferencedTableName(SQLName_ptr value)
{
  if (value == NULL)
  {
    this->referencedTable = NULL;
    return;
  }
  this->setReferencedTable(SQLExprTableSource_ptr(new SQLExprTableSource(std::dynamic_pointer_cast<SQLExpr>(value))));
}

void SQLForeignKeyImpl::setReferencedTable(SQLExprTableSource_ptr x)
{
  if (x != NULL)
  {
    x->setParent(SharedObject(SQLForeignKeyImpl));
  }
  this->referencedTable = x;
}

SQLName_list_ptr SQLForeignKeyImpl::getReferencedColumns()
{
  return referencedColumns;
}

BOOL_ptr SQLForeignKeyImpl::isOnDeleteCascade()
{
  return onDeleteCascade;
}

void SQLForeignKeyImpl::setOnDeleteCascade(BOOL_ptr onDeleteCascade)
{
  this->onDeleteCascade = onDeleteCascade;
}

BOOL_ptr SQLForeignKeyImpl::isOnDeleteSetNull()
{
  return onDeleteSetNull;
}

void SQLForeignKeyImpl::setOnDeleteSetNull(BOOL_ptr onDeleteSetNull)
{
  this->onDeleteSetNull = onDeleteSetNull;
}

BOOL_ptr SQLForeignKeyImpl::isDisableNovalidate()
{
  return disableNovalidate;
}

void SQLForeignKeyImpl::setDisableNovalidate(BOOL_ptr disableNovalidate)
{
  this->disableNovalidate = disableNovalidate;
}

void SQLForeignKeyImpl::accept0(SQLASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(SQLForeignKeyImpl)))
  {
    acceptChild(visitor, this->getName());
    acceptChild(visitor, this->getReferencedTableName());
    SQLObject_list_ptr tmp1 = ListTran::tran_class<SQLName, SQLObject>(this->getReferencingColumns());
    acceptChild(visitor, tmp1);
    SQLObject_list_ptr tmp2 = ListTran::tran_class<SQLName, SQLObject>(this->getReferencedColumns());
    acceptChild(visitor, tmp2);
  }
  visitor->endVisit(SharedObject(SQLForeignKeyImpl));
}

void SQLForeignKeyImpl::cloneTo(SQLForeignKeyImpl_ptr x)
{
  SQLConstraintImpl::cloneTo(std::dynamic_pointer_cast<SQLConstraintImpl>(x));

  if (referencedTable != NULL)
  {
    x->setReferencedTable(std::dynamic_pointer_cast<SQLExprTableSource>(referencedTable->clone()));
  }

  for (SQLName_ptr column : *referencingColumns)
  {
    SQLName_ptr columnClone = std::dynamic_pointer_cast<SQLName>(column->clone());
    columnClone->setParent(x);
    x->getReferencingColumns()->push_back(columnClone);
  }

  for (SQLName_ptr column : *referencedColumns)
  {
    SQLName_ptr columnClone = std::dynamic_pointer_cast<SQLName>(column->clone());
    columnClone->setParent(x);
    x->getReferencedColumns()->push_back(columnClone);
  }
}

SQLObject_ptr SQLForeignKeyImpl::clone()
{
  SQLObject_ptr clone_tmp = std::shared_ptr<SQLForeignKeyImpl>(new SQLForeignKeyImpl());
  std::shared_ptr<SQLForeignKeyImpl> x = std::dynamic_pointer_cast<SQLForeignKeyImpl>(clone_tmp);
  // SQLForeignKeyImpl *x = new SQLForeignKeyImpl();
  cloneTo(x);
  return x;
}
